<template>
  <div class="parameter-edit">
    <el-tabs v-model="activeTab" type="border-card" :addable="false" @tab-remove="handleTabRemove">
      <el-tab-pane
        v-for="(tab, index) in tabs"
        :key="tab.name"
        v-model="activeTab"
        :label="tab.changed ? '* ' + tab.tableName : tab.tableName"
        :name="tab.name"
        :closable="index !== 0"
        @tab-remove="handleTabRemove"
      >
        <el-row v-loading="loading">
          <el-col>
            <div id="content" class="min-h-[500] overflow-auto">
              <el-form ref="form" :model="tab.form" :size="size" :name="tab.name" @submit.native.prevent>
                <grid-layout
                  ref="gridlayout"
                  :layout.sync="tab.layout"
                  :col-num="3"
                  :row-height="28"
                  :min-h="2"
                  :is-draggable="false"
                  :is-resizable="false"
                  :is-mirrored="false"
                  :auto-size="false"
                  :vertical-compact="true"
                  :margin="[10, 8]"
                  :use-css-transforms="true"
                >
                  <grid-item
                    v-for="item in tab.layout"
                    :key="item.i"
                    style="touch-action: none"
                    :x="item.x"
                    :y="item.y"
                    :w="item.w"
                    :h="item.h"
                    :i="item.i"
                  >
                    <parameter-card
                      editable
                      :closable="false"
                      :item="item"
                      :form="tab.form"
                      v-bind="$attrs"
                      :template-id="templateId"
                      :disabled="item.paramPermissionControl === 0"
                      :reference-values="referenceValues"
                      @undo="() => undo(item, tab.form)"
                      @select-file="() => { activeId = item.i; uploadFileVisible = true }"
                      @click.native="() => activeId = item.i"
                      @select-reference="(item) => handleReferenceClick(item)"
                    />

                    <!-- @select-reference="(item) => $emit('reference-click', item)" -->
                    <!-- @select-reference="(id) => handleSelectReference(id)" -->
                  </grid-item>
                </grid-layout>
              </el-form>
            </div>
          </el-col>
        </el-row>
      </el-tab-pane>
    </el-tabs>

    <upload-file
      :current-item="currentItem"
      append-to-body
      v-model="uploadFileVisible"
      @confirm="(filePath) => handleFileUploadConfirm(filePath)"
    />
    <select-reference
      append-to-body
      v-model="selectReferenceVisible"
      :table-id="currentItem ? currentItem.refTableSchemaId : ''"
      :current-item="currentItem"
      :has-param="true"
      :template-id="templateId"
    />
  </div>
</template>

<script>
import { types } from '../constant.js'
import ParameterCard from './parameter'
import VueGridLayout from 'vue-grid-layout'
import UploadFile from './upload-file'
import SelectReference from './select-reference'
import { formatDateParameter, parseDate } from '../helper'
import {
  getReferenceEntryRecord,
  getEntryLayoutConfig,
  getEntryByName,
  getTerminalEntryByName,
  getLayoutConfigFromReferenceTable,
  saveMultipleProfileEntryLayout,
  saveReferenceLayoutConfig,
  getTemplateTableLayoutList,
  addProfileEntry
} from '@/api/parameter'
import { isObjectBoolean } from '@/utils'
import { deleteCustomize } from '@/api/cmd'

let unwatch = () => { }

let layoutRequest = () => { }
let paramName = ''

export default {
  name: 'ParameterEdit',
  components: {
    GridLayout: VueGridLayout.GridLayout,
    GridItem: VueGridLayout.GridItem,
    ParameterCard,
    UploadFile,
    SelectReference
  },
  inheritAttrs: false,
  props: {
    appName: {
      type: String
    },
    sn: {
      type: String
    },
    tableId: {
      type: String
    },
    type: {
      type: String
    },
    entityName: {
      type: String
    },
    referenceTable: {
      type: Array
    },

    size: {
      type: String,
      default: 'mini'
    },
    templateId: String,
    scheduleUuid: String
  },
  data() {
    return {
      layout: [],
      tabs: [],
      activeTab: '',
      referenceValues: [],
      activeId: '',
      entityId: '',
      paramId: '',
      uploadFileVisible: false,
      selectReferenceVisible: false,
      refTableSchemaId: '',
      buttonLoading: false,
      form: {},
      loading: false,
      profileNotExist: false
    }
  },
  computed: {
    hasChanged() {
      const tabs = this.tabs.filter((tab) => tab.changed)
      return tabs.length > 0
    },
    currentItem() {
      // return this.layout.find((item) => item.i === this.activeId)
      if (this.currentTab) {
        return this.currentTab.layout.find((item) => item.i === this.activeId)
      } else return {}
    },
    currentTab() {
      return this.tabs.find((tab) => tab.name === this.activeTab)
    },
    dataString() {
      if (this.currentTab) {
        return JSON.stringify(
          this.currentTab.layout.map((_) => ({
            paramValues: _.paramValues || ''
          }))
        )
      }
      return ''
    }
  },
  mounted() {
    if (this.$parent.$options.name === 'ElDialog') {
      this.$emit('init')
    } else {
      this.handleOpen()
    }
  },
  methods: {
    // 这个函数是获取信息，判断要使用哪个接口layoutRequest来获取布局配置
    handleOpen(tableId = this.tableId, sourceEntityName = this.entityName, paramId, sourceEntityId, param) {
      let getRequest
      if (this.type === 'terminalTable') {
        getRequest = getTerminalEntryByName
      } else {
        getRequest = getEntryByName
      }
      this.loading = true
      getRequest(this.templateId, tableId, sourceEntityName).then(async(data) => {
        const _data = data || {}
        let entityId = ''
        if (!data) { // subProfile不存在的情况下
          if (this.tableId !== tableId) {
            // 因为subProfile没有数据，所以需要给paramValues赋值，否则后端关联关系会出问题
            param.paramValues = [sourceEntityName]
            // 创建Entry
            try {
              const { id } = await addProfileEntry({
                templateId: this.templateId,
                tableId: tableId,
                rowUniqueKey: sourceEntityName,
                isTerminal: false,
                sourceTableId: this.currentTab.tableId,
                sourceEntityId: sourceEntityId,
                sourceParamId: this.paramId
              })
              this.entityId = entityId = id
            } catch (err) {
              this.loading = false
              return this.$confirmError(err)
            }

            const table = this.referenceTable.find(
              (_) => _.id === this.refTableSchemaId
            )
            if (table) {
              _data.id = table.id
              _data.tableName = table.name
            }
            if (this.type === 'terminalTable') {
              layoutRequest = getEntryLayoutConfig
            } else {
              layoutRequest = getLayoutConfigFromReferenceTable
            }
            console.log(sourceEntityId)
            this.fetchLayoutConfigFromReferenceTable(
              { id: entityId, tableName: _data.tableName },
              tableId,
              entityId,
              sourceEntityName,
              paramId,
              entityId,
              sourceEntityId
            )
          } else {
            // Profile表不存在的情况下
            this.profileNotExist = true
            _data.tableName = 'Profile'
            layoutRequest = getTemplateTableLayoutList
            this.fetchLayoutConfigFromReferenceTable(
              _data,
              tableId,
              _data.id,
              sourceEntityName,
              paramId,
              entityId,
              sourceEntityId
            )
          }
        } else {
          this.entityId = entityId = data.id
          if (this.type === 'terminalTable') {
            layoutRequest = getEntryLayoutConfig
          } else {
            layoutRequest = getLayoutConfigFromReferenceTable
          }
          this.fetchLayoutConfigFromReferenceTable(
            _data,
            tableId,
            _data.id,
            sourceEntityName,
            paramId,
            entityId,
            sourceEntityId
          )
        }
      })
    },
    handleClose(e) {
      if (this.tabs.filter((tab) => tab.changed).length > 0) {
        this.$commonConfirm({
          title: this.$t('flyparam.close_tab'),
          type: 'danger',
          showIcon: false,
          content: this.$t('flyparam.unsave_warning'),
          btnSureTitle: this.$t('flyparam.unsave_close'),
          onConfirm: (instance, done) => {
            this.close()
            done()
          }
        })
      } else {
        this.close()
      }
    },
    // 这个函数请求布局配置
    fetchLayoutConfigFromReferenceTable(
      data,
      tableId,
      name,
      entityName,
      paramId,
      entityId,
      sourceEntityId
    ) {
      layoutRequest(this.templateId, tableId, data.id)
        .then((res) => {
          this.loading = false
          unwatch = this.$watch(
            (vm) => vm.dataString,
            function() {
              if (this.currentTab.reserveJSON !== this.dataString) {
                this.$set(this.currentTab, 'changed', true)
              } else {
                this.$set(this.currentTab, 'changed', false)
              }
            }
          )

          const form = {}
          const layout = res.map((item) => {
            let table

            if (item.valueType === 5) {
              const refTable = this.referenceTable.find(
                (table) => table.id === item.refTableSchemaId
              )
              if (refTable) {
                table = {
                  id: item.refTableSchemaId,
                  tableType: refTable.tableType
                }
              }
            }

            let paramValues

            if (item.type !== 2) {
              // 确定要用的指是来自defualtValues还是paramValues
              if (!item.paramValues) {
                paramName = 'defaultValues'
              } else if (this.valueType === 5) {
                if (item.paramValues && item.paramValues.length > 0 && item.paramValues[0] === '') {
                  paramName = 'defaultValues'
                } else {
                  paramName = 'paramValues'
                }
              } else if (item.paramValues && item.paramValues.length === 0) {
                paramName = 'defaultValues'
              } else {
                paramName = 'paramValues'
              }

              if (item.valueType === 5) {
                if (this.$attrs.preview) {
                  paramValues = item[paramName].map((_) => _.name)
                } else {
                  paramValues = item[paramName].filter(_ => _.length > 0)
                }
              } else if ([types.DATE, types.DATETIME].includes(item.valueType) && item[paramName][0]) { // 日期类型特殊处理
                if (paramName === 'paramValues') {
                  if (item.curValueType !== item.valueType) {
                    paramValues = ''
                  } else {
                    paramValues = parseDate(item.paramValues[0], item.formatter)
                  }
                } else {
                  paramValues = parseDate(item.defaultValues[0], item.formatter)
                }
              } else {
                try {
                  paramValues = isObjectBoolean(item[paramName][0]) ? item[paramName][0] : (item[paramName][0] || '')
                } catch (err) {
                  console.log(item)
                }
              }
            }

            return {
              ...item,
              i: item.paramLayoutId,
              title: item.title,
              valueType: item.valueType,
              type: item.type,
              w: item.w,
              y: item.y,
              x: item.x,
              h: item.h,
              label: item.label,
              table: table,
              edit: false,
              paramValues,
              paramDefault: paramName === 'defaultValues',
              defaultValues: item.type !== 2 ? item.defaultValues[0] : ''
            }
          })

          // 填充form数据
          layout.forEach((data) => {
            form[data.i] = isObjectBoolean(data.paramValues) ? data.paramValues : (data.paramValues || '')
          })
          console.log(this.tabs)
          if (!this.tabs.find((tab) => tab.name === name)) {
            const tab = {
              name: name || tableId,
              entityId,
              layout,
              tableId,
              form,
              entityName: this.sn,
              changed: false,
              reserveJSON: JSON.stringify(
                layout.map((_) => ({
                  paramValues: _.paramValues || ''
                }))
              )
            }

            if (paramId) {
              tab.sourceTableId = this.currentTab.tableId
              tab.sourceEntityId = sourceEntityId
              // tab.sourceEntityName = this.sn + '~' + data.id.split('-')[1] + '~' + paramId.split('-')[1]
              tab.sourceEntityName = entityName
              tab.sourceParamId = this.paramId
            }

            this.tabs.push(tab)
          }

          this.activeTab = name || tableId
          this.currentTab.tableName = data.tableName || data.name
        })
        .catch((err) => {
          this.loading = false
          this.$message.error(err.message)
        })
    },
    undo(item, form) {
      const timeTypes = [types.DATETIME, types.DATE, types.TIME]
      if (timeTypes.indexOf(item.valueType) > -1) {
        item.paramValues = item.defaultValues
      } else {
        this.$set(form, item.i, item.defaultValues)
      }
    },

    beforeSave() {
      return new Promise((resolve, reject) => {
        this.$commonConfirm({
          // TODO 国际化
          title: 'Param Configuration',
          content: 'This action will publish the app. Are you sure to continue?',
          btnSureTitle: this.$t('common.confirm'),
          onConfirm: (instance, done) => {
            instance.loading = true
            return resolve(done)
          }
        })
      })
    },

    async save() {
      const forms = this.$refs.form
      // const tabs = this.tabs.filter((tab) => tab.changed)
      const tabs = this.tabs
      if (this.type === 'terminalTable') {
        let valid = true

        forms.forEach((form, index) => {
          form.validate((_valid) => {
            if (!_valid) {
              valid = _valid
              this.activeTab = form.$attrs.name
            }
          })
        })

        if (valid) {
          const done = await this.beforeSave()
          this.$emit('loading', true)
          const arr = []
          const param = []

          tabs.forEach((tab) => {
            let paramValues
            const layout = tab.layout.filter((item) => item.paramPermissionControl === 0 || item.type !== 2)
            const obj = {}
            const data = layout.map((item) => {
              if (item.valueType === 5) {
                paramValues = item.paramValues || []
              } else if ((item.valueType === types.DATE || item.valueType === types.DATETIME) && item.paramValues) {
                const value = formatDateParameter(item, 'paramValues')
                paramValues = value ? [value] : []
              } else {
                paramValues = [item.paramValues]
              }

              return {
                paramId: item.paramId,
                paramValues
              }
            })
            arr.push(data)
            obj.tableId = tab.tableId
            obj.sourceTableId = tab.sourceTableId
            obj.sourceEntityName = tab.sourceEntityName
            obj.sourceEntityId = tab.sourceEntityId
            obj.sourceParamId = tab.sourceParamId
            obj.paramValueUpdateDtos = data
            param.push(obj)
          })

          try {
            await saveMultipleProfileEntryLayout(
              this.templateId,
              this.tableId,
              this.sn,
              this.scheduleUuid,
              param
            )
            this.$message.success(this.$t('flyparam.msg_saveSucceed'))
            this.$emit('save')
            this.close()
            this.$emit('loading', false)
          } catch (err) {
            done()
            if (err.message) {
              this.$message.error(err.message)
            }
            this.$emit('loading', false)
          }
          done()
        }
      } else if (this.type === 'refTable') {
        forms.forEach((form, index) => {
          form.validate(async(valid) => {
            if (valid) {
              let paramValues
              const layout = this.currentTab.layout.filter(
                (item) => item.type !== 2
              )
              const params = {
                templateId: this.templateId,
                tableId: this.currentTab.tableId,
                entityId: this.activeTab,
                data: layout.map((item) => {
                  if (item.valueType === 5) {
                    paramValues = item.paramValues || []
                  } else if ((item.valueType === types.DATE || item.valueType === types.DATETIME) && item.paramValues) {
                    const value = formatDateParameter(item, 'paramValues')
                    paramValues = value ? [value] : []
                  } else {
                    paramValues = [item.paramValues]
                  }

                  return {
                    paramId: item.paramId,
                    paramValues
                  }
                })
              }

              try {
                await saveReferenceLayoutConfig(params)
                this.$message.success(this.$t('flyparam.msg_saveSucceed'))
                this.$emit('save')
                this.close()
              } catch (err) {
                this.$message.error(err.message)
              }
            }
          })
        })
      }
    },
    close() {
      unwatch()
      this.$emit('close')
      this.layout = []
      this.activeTab = ''
      this.tabs = []
    },
    // 关闭tab的回调
    handleTabRemove(id) {
      const removeTab = () => {
        // 选中第一个tab
        this.activeTab = this.tabs[0].name
        // 移除tab
        this.tabs = this.tabs.filter((tab) => tab.name !== id)
      }

      if (this.currentTab.changed) {
        this.$commonConfirm({
          title: this.$t('flyparam.close_tab'),
          content: this.$t('flyparam.unsave_warning'),
          btnSureTitle: this.$t('common.confirm'),
          onConfirm: (instance, done) => {
            removeTab()
            done()
          }
        })
      } else {
        removeTab()
      }
    },
    handleFileUploadConfirm(filePath) {
      const item = this.currentTab.layout.find(
        (item) => item.i === this.activeId
      )
      this.$set(this.currentTab.form, item.i, filePath)
      this.$refs.form[0].validateField(item.i, () => {})
      this.$set(item, 'paramValues', filePath)
    },

    /** 点击引用类型的参数
     * @param {Object} item 点击的引用类型实例
     */
    handleReferenceClick(item) {
      this.activeId = item.i
      this.paramId = item.paramId
      this.refTableSchemaId = item.refTableSchemaId
      if (item.table.tableType === 1) {
        if (this.profileNotExist) {
         return this.$confirm(this.$t('flyparam.subprofile_click_tip', { appName: this.appName, devSn: this.sn }), this.$t('common.tips'), {
            confirmButtonText: this.$t('page.confirm'),
            cancelButtonText: this.$t('page.cancel'),
            type: 'warning'
          }).then(() => {
            this.loading = true
            addProfileEntry({
              templateId: this.templateId,
              tableId: this.tableId,
              rowUniqueKey: this.sn,
              isTerminal: true
            })
              .then((newEntry) => {
                this.profileNotExist = false
                this.currentTab.entityId = newEntry.id
                this.$message.success(this.$t('common.message.operation_success'))
              })
              .catch((err) => {
                this.$message.error(err.message)
              })
              .finally(() => {
                this.loading = false
              })
          }).catch(() => {
          })
        }
        let sourceEntityName = ''
        const sourceEntityId = this.currentTab.entityId // sourceEntityId使用的是当前tab的entityId
        if (this.type === 'terminalTable') {
          sourceEntityName = `${this.sn}~${sourceEntityId?.split('-')[1]}~${item.paramId?.split('-')[1]}`
        }
        // 打开新的tab
        this.handleOpen(item.refTableSchemaId, sourceEntityName, item.paramId, sourceEntityId, item)
      } else if (item.table.tableType === 2) {
        if (item.table) {
          this.selectReferenceVisible = true
        }
      }
    }
  }
}
</script>

<style>
.parameter-card>>>.el-divider--horizontal {
  margin: 5px 0;
}
</style>

<style scoped lang="scss">
.parameter-edit::v-deep .el-form-item.form-item__string.is-error .el-form-item__error {
  transform: translateY(8px);
}
</style>
